/**
 * Holds some Globals setting and a some CAP/Phrap stuff
 */
package jpave.dataholders;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;
import java.security.AccessController;
import java.security.PrivilegedAction;

import javax.swing.JApplet;

import util.Debug.ErrorReport;
import util.methods.HostsCfg;
import util.methods.PaveProps;
import util.methods.ProcessHelpers;
import util.methods.StringHelpers;
import util.methods.UIHelpers;
import jpave.textfile.CAP3AceFileReader;

public class GlobalSettings 
{
	public static final String HOSTS = "HOSTS.cfg";
	public static final String STCWCFG = "sTCW.cfg";
	public static final String LIBCFG = "LIB.cfg";
	public static final String STCW = "sTCW_"; // database prefix
	
	public static final String STRING_CONFIGURATION_DESCRIPTION = 
		"Configuration Settings for viewSingleTCW";
	
	public static final String CAP3_PATH = "cap3_path";
	public static final String PHRAP_PATH = "phrap_path";	
	public static final String BLAST_PATH = "blast_path";	
	final String CAP3_DEF = PaveProps.getExtDir() + "/CAP3/cap3";
	
	public boolean isUseCookieForPrefs ( ) { 
		return applet != null && appletDebug == false; }
	
	public boolean isApplet ( ) { return applet != null; }

	/**
	 * @return location of the .jpave directory
	 */
	static public String getJPaveTempPath()
	{
		try 
		{
			if (!UIHelpers.isApplet()) 
			{
				return new File(".").getCanonicalPath() + "/.jpave";
			}
			else 
			{
				//System.out.println("Getting temp path...");
				
				File tf2 = (File) AccessController.doPrivileged(new PrivilegedAction() 
				{
					public Object run() 
					{
						File tf = null;
						try
						{
							tf = File.createTempFile("jpave", Long.toString(System.nanoTime()));
							if (tf == null)
							{
								//System.out.println("null temp file");
								//Thread.sleep(100000);
							}
							//System.out.println(tf.getCanonicalPath());
							if (tf.exists()) tf.delete();
							tf.mkdir();
							tf.deleteOnExit();	
						}
						catch(Exception e)
						{
							System.out.println("********Could not create temp file!!**********");
							System.out.println(e.getStackTrace());
						}
						//try{Thread.sleep(100000);}catch(Exception e2){} // give time to read it
						
						return (Object)tf;
					}
				});
				
				return tf2.getAbsolutePath();
			}
		}
		catch (Exception e) 
		{
			ErrorReport.reportError(e,"Error: cannot find .jpave directory");
			return null;
		}
	}

	/**
	 * called from JPaveMain
	 * Load the settings from the jpave.config (HOSTS.cfg) file
	 */
	public void loadFromHosts ( ) 
    {
		try
		{
			HostsCfg hosts = new HostsCfg();
			allSessions = SessionData.createPAVElistForHost(hosts.host );
		
			pathCAP3 = hosts.getCapPath(); 
			pathPHRAP = hosts.getPhrapPath(); 
		}
		catch(Exception e)
		{
			System.err.println("Error loading HOSTS.cfg");
			e.printStackTrace();
			System.exit(0);
		}
	
    }
	
	/********** CAP AND PHRAP METHODS  *********/
	/*
	 * CAPorPhrapTab.alignESTs: 
	 * Execute alignment program and store in a cluster
	 */
    public MainData executeCAPorPHRAP ( String strCommand,
    										TreeSet<String> estList,
    										String strOptions,
    										int recordNum) throws Exception
    {    
	    	String strContigName;
	    	String strSingletonName = "Singleton";
	    	
	    	if(strCommand.equals("phrap"))
	    		strContigName = "PHRAP";
	    	else
	    		strContigName = "CAP3";
	    	
	    	strContigName += " #" + (recordNum+1) + ".";
	    	
	    	// Execute alignment program
	    	BufferedReader aceOutFile = null;
	    		aceOutFile = executeCAPorPHRAPLocally ( strCommand, estList, strOptions );
	    	if ( aceOutFile == null )
	    		return null;
	    	 
	    	// Parse the output ACE file:
	    	MainData theCluster = CAP3AceFileReader.readClusterFrom( aceOutFile, 
	    			selectedSession, estList, strContigName, strSingletonName );
	    	theCluster.setClusterID( "Alignment Results" );
	    	return theCluster;
    }
    
    private BufferedReader executeCAPorPHRAPLocally ( String strCommand,
												    		TreeSet<String> estList,
												    		String strOptions ) throws Exception
    {
	    	String strFASTAName = "/tmp/tempFASTA";
	    	File aceOutFile = new File ( strFASTAName + ".ace" );
	    	File singletsOutFile  = new File ( strFASTAName + ".singlets" );
	    	if ( strCommand.equals( "cap3" ) ) 
	    	{
	    		aceOutFile = new File ( strFASTAName + ".cap.ace" );
	            singletsOutFile = new File ( strFASTAName + ".cap.singlets" );	
	    	}
	    	File basesFASTA = new File ( strFASTAName );
	    	File qualFASTA  = new File ( strFASTAName + ".qual" );
	    	String str="<command>";
	    	
	    	try
	    	{	
	    		// Create the FASTA files with the selected sequences
	    		PrintStream seqStream = new PrintStream ( new FileOutputStream( basesFASTA ) );
	    		PrintStream qualStream = new PrintStream ( new FileOutputStream( qualFASTA ) );
	    		Vector<SequenceData> clones = selectedSession.loadClones( estList );
	    		Iterator<SequenceData> iterClone = clones.iterator();
	    		while ( iterClone.hasNext() )
	    		{
	    			SequenceData seq = (SequenceData)iterClone.next();
	    			seq.appendToFASTAFiles( seqStream, qualStream );
	    		}
	    		
	    		seqStream.close();
	    		qualStream.close();	
	    		
	    		// Run the alignment
	    		str = getPathToBinary ( strCommand );
	    		str += " " + basesFASTA.getAbsolutePath();
	    		str += " " + strOptions;
	    		if ( strCommand.equals("phrap" ) ) 
	    			str += " -ace";
	
	    		// System.err.println("CAP3 execute: " + str);
	    		int nExitState = ProcessHelpers.runCommand ( str );
	    		if ( nExitState == Integer.MIN_VALUE )
	    			return null;
	    		if ( nExitState > 0 )
	    			System.err.println ( "Application exited with " + nExitState + "." ); 
							
	    		return new BufferedReader ( new FileReader ( aceOutFile ) );    
	    	} catch (Throwable e) {
	    		String s = "Error: cannot execute " + strCommand + " command: " + str;
	    		System.err.println(s);
				ErrorReport.reportError(e, s);
	    	}
	    	finally
	    	{        
	    		// Delete all temporary files
	    		if ( strCommand.equals( "phrap" ) ) 
	    		{
		    		File contigsOutFile  = new File ( strFASTAName + ".contigs" );
		    		File qualOutFile  = new File ( strFASTAName + ".contigs.qual" );
		    		File problemsOutFile  = new File ( strFASTAName + ".problems" );
		    		File problemsQualOutFile  = new File ( strFASTAName + ".problems.qual" );
		    		File logOutFile  = new File ( strFASTAName + ".log" );
		    		
		    		contigsOutFile.delete();
		    		problemsOutFile.delete();
		    		problemsQualOutFile.delete();
		    		qualOutFile.delete();
		    		logOutFile.delete();	    		
	    		}
	    		else
	    		{
	        		File contigsOutFile  = new File ( strFASTAName + ".cap.contigs" );
	        		File linksOutFile  = new File ( strFASTAName + ".cap.contigs.links" );
	        		File qualOutFile  = new File ( strFASTAName + ".cap.contigs.qual" );
	        		File infoOutFile  = new File ( strFASTAName + ".cap.info" );
	        		
	        		contigsOutFile.delete();
	        		linksOutFile.delete();
	        		qualOutFile.delete();
	        		infoOutFile.delete();
	        	}
	    		
	    		singletsOutFile.delete();
	    		basesFASTA.delete();
	    		qualFASTA.delete();	
	    		aceOutFile.delete();
	    	}
	    	return null;
    }
    
	public boolean canCallCAP3 () { return canCall ( "cap3" ); }; 
	public boolean canCallPHRAP () { return canCall (  "phrap" ); }; 

    private boolean canCall(String strCommand) {
		
	    	String s = getPathToBinary(strCommand); 
	    	if (s == null) return false;
	    	else return true;
	}
    
    private String getPathToBinary ( String strCommand )
    {
	    	// Map the command name to the correct data member
	    	String str = null;
	    	if ( strCommand.equals(  "cap3" ) ) {
	    		str = pathCAP3;
	    		if (str.startsWith("#") || StringHelpers.isEmpty(str)) str = CAP3_DEF; // CAS 4/12/13
	    	}
	    	else if ( strCommand.equals(  "phrap" ) ) 
	    		str = pathPHRAP;
	    	else
	    		return null;
	    	
	    	// Validate the path
	    	if ( StringHelpers.isEmpty ( str ) ) {
	    		if (prtNoPath==false) { // CAS 7Nov11
	    			//System.err.println( "Warning: The path to " + strCommand +  
	    			//	" is empty; check " + JPAVE_HOSTS);
	    			prtNoPath = true;
	    		}
	    		return null;
	    	}
	    	File filePath = new File ( str );
	    	if ( !filePath.isFile() || !filePath.exists() ) {
	    		if (prtNoPath==false) { // CAS 7Nov11
	    			//System.err.println( "Warning: The path to " + strCommand +  
	    			//	" is not valid; check " + JPAVE_HOSTS);    		
	    			prtNoPath = true;
	    		}
	    		return null;
	    	}
	    	return str;
    }
    
	private static String pathCAP3 = null;
	private static String pathPHRAP = null;
	
	// Settings used by applets
	transient JApplet applet = null;
	transient boolean appletDebug = false;
	
	// The session to be viewed
	transient SessionData selectedSession = null;
	
	// The list of all sessions (can be empty as when using the applet)
	transient Vector<SessionData> allSessions = new Vector<SessionData> ();
	
	public String getPathCAP3() { return pathCAP3; }
	//public void setPathCAP3(String pathCAP3) { this.pathCAP3 = pathCAP3; }
	public String getPathPHRAP() { return pathPHRAP; }
	//public void setPathPHRAP(String pathPHRAP) { this.pathPHRAP = pathPHRAP; }
	private boolean prtNoPath = false;
	
	public Vector<SessionData> getAllSessions() { return allSessions; }
	public SessionData getSelectedSession() { return selectedSession; }
	public void setSelectedSession(SessionData selectedSession) { this.selectedSession = selectedSession; }
	
	public JApplet getApplet() { return applet; }
	public void setApplet(JApplet applet) { this.applet = applet; }
	public boolean isAppletDebug() { return appletDebug; }
	public void setAppletDebug(boolean appletDebug) { this.appletDebug = appletDebug; }
}

